package com.jmp.autocofiguration.web.filter;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import one.stand.entity.TokenEntity;
import one.stand.service.user.TokenService;
import one.stand.util.IpUtil;
import one.stand.util.RequestContext;
import one.stand.util.RequestContextHolder;
import org.apache.commons.lang3.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * 认证请求，获取用户信息
 *
 * @author cjr
 */
//@WebFilter(urlPatterns = "/*", filterName = "securityFilter")
//@Order(2)
@Slf4j
public class SecurityFilter extends OncePerRequestFilter {
    public static String HEADER_TOKEN_FEIGN = "x-feign-token";//feign内部传参
    public static String HEADER_TOKEN_JMP = "token";//金名片接口凭证key
    private static final String X_EQU_CODE = "x-equCode";
    private static final String X_VERSION = "x-version";
    private static final String X_PLATFORM = "x-platform";
    private static final String HEADER_COMPANYKEY = "companyKey";

    private TokenService tokenService;

    public SecurityFilter(TokenService tokenService) {
        this.tokenService = tokenService;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        RequestContext requestContext = new RequestContext();

        setRequest(requestContext, request);

        try {
            String token = requestContext.getRequest().getToken();
            TokenEntity tokenEntity = getTokenEntity(token);
            setUserInfo(requestContext, tokenEntity);
            String loginEnum = Objects.nonNull(requestContext.getUser()) ? requestContext.getUser().getLoginProgramName() : StringUtils.EMPTY;
            log.info("client({}/{}/{}/{}): {}", requestContext.getRequest().getCompanyKey(), requestContext.getRequest().getEquCode(), requestContext.getRequest().getClientPlatform(), loginEnum, token);

            RequestContextHolder.setRequestContext(requestContext);

            filterChain.doFilter(request, response);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            throw e;
        } finally {
            RequestContextHolder.reset();
        }
    }

    private void setUserInfo(RequestContext requestContext, TokenEntity tokenEntity) {
        if (log.isDebugEnabled()) {
            log.debug("token info: {}", JSON.toJSONString(tokenEntity));
        }
        if (Objects.nonNull(tokenEntity)) {
            requestContext.setLogin(true);
            RequestContext.User user = RequestContext.User.builder()
                    .companyKey(tokenEntity.getCompanyKey())
                    .userId(Objects.nonNull(tokenEntity.getId()) ? tokenEntity.getId().intValue() : null)
                    .companyId(Objects.nonNull(tokenEntity.getCId()) ? tokenEntity.getCId().intValue() : null)
                    .cardId(Objects.nonNull(tokenEntity.getMyCardId()) ? tokenEntity.getMyCardId() : null)
                    .roleId(tokenEntity.getRoleId())
                    .loginProgramName(tokenEntity.getLoginProgramName())
                    .sessionKey(tokenEntity.getSessionKey())
                    .build();
            requestContext.setUser(user);
            requestContext.setCard(Objects.nonNull(user) && Objects.nonNull(user.getCardId()));
            requestContext.getRequest().setEquCode(tokenEntity.getEquCode());
        }
    }

    private TokenEntity getTokenEntity(String token) {
        TokenEntity tokenEntity = null;
        if (Objects.nonNull(token)) {
            TokenEntity result = tokenService.getTokenfo(token);
            if (Objects.nonNull(result)) {
                tokenEntity = result;
            } else {
                log.warn("token({}) info is null", token);
            }
        }
        return tokenEntity;
    }

    private void setRequest(RequestContext requestContext, HttpServletRequest request) {
        String token = getToken(request);
        String equCode = request.getHeader(X_EQU_CODE);
        String version = request.getHeader(X_VERSION);
        String clientPlatform = request.getHeader(X_PLATFORM);
        String companyKey = request.getHeader(HEADER_COMPANYKEY);

        RequestContext.Request contextRequest = RequestContext.Request.builder()
                .ip(IpUtil.getIpAddr(request))
                .token(token)
                .equCode(equCode)
                .companyKey(companyKey)
                .version(version)
                .clientPlatform(clientPlatform)
                .build();
        requestContext.setRequest(contextRequest);
    }

    private String getToken(HttpServletRequest request) {
        String token = request.getHeader(HEADER_TOKEN_JMP);
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader(HEADER_TOKEN_FEIGN);
        }
        if (StringUtils.isEmpty(token)) {
            token = request.getHeader(HttpHeaders.AUTHORIZATION);
        }
        return token;
    }
}